package com.shouyun.modules.oss.controller;

import com.alibaba.fastjson.JSONObject;
import com.shouyun.common.annotation.LogOperation;
import com.shouyun.common.utils.DataUtils;
import com.shouyun.common.utils.Result;
import com.shouyun.modules.oss.dto.Chunk;
import com.shouyun.modules.oss.dto.FileInfo;
import com.shouyun.modules.oss.service.OssService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 文件上传
 *
 * @author Sunshouguo sunshouguo_java@163.com
 */
@RestController
@RequestMapping("sys/oss")
public class SysOssController {
    @Autowired
    private OssService ossService;

    /**
     * 新建文件夹
     *
     * @param params
     * @return
     */
    @PostMapping("createDir")
    public Result upload(@RequestBody Map<String, String> params) {
        String path = params.get("path");
        if (StringUtils.isBlank(path)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);
        File file = new File(workspace);
        if (file.exists() && file.isDirectory()) {
            return new Result().error("文件已存在");
        }
        if (!com.shouyun.common.utils.FileUtils.mkdirs(workspace)) {
            return new Result().error("创建失败");
        }
        return new Result();
    }

    /**
     * 重命名
     *
     * @param params
     * @return
     */
    @PostMapping("reName")
    public Result reName(@RequestBody Map<String, String> params) {
        String path = params.get("path");
        String fileName = params.get("fileName");
        if (StringUtils.isBlank(path) || StringUtils.isBlank(fileName)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);

        File file = new File(workspace);
        if (!file.exists()) {
            return new Result().error("文件不存在");
        }
        return com.shouyun.common.utils.FileUtils.renameTo(workspace, fileName);
    }

    /**
     * 删除文件
     *
     * @param params
     * @return
     */
    @PostMapping("deleteFile")
    public Result deleteFile(@RequestBody Map<String, String> params) {
        String path = params.get("path");
        if (StringUtils.isBlank(path)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);

        File file = new File(workspace);
        if (!file.exists()) {
            return new Result().error("文件不存在");
        }
        if (!com.shouyun.common.utils.FileUtils.delete(workspace)) {
            return new Result().error("删除失败");
        }
        return new Result();
    }

    /**
     * 文件列表
     *
     * @param params
     * @return
     */
    @GetMapping("list")
    public Result page(@RequestParam Map<String, String> params) {
        String order = params.get("order");
        String path = params.get("path");
        if (StringUtils.isBlank(path)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);
        //返回信息
        List<FileInfo> fileInfoList = new ArrayList<>();
        File fileDir = new File(workspace);
        if (fileDir.exists()) {
            FileInfo fileInfo = null;
            List<File> files = orderByName(fileDir.listFiles());
            for (File file : files) {
                fileInfo = new FileInfo();
                fileInfo.setName(file.getName());
                fileInfo.setIsDir(file.isDirectory());
                fileInfo.setSize(file.length());
                int suffixIndex = fileInfo.getName().lastIndexOf(".");
                if (suffixIndex > 0) {
                    fileInfo.setSuffix(fileInfo.getName().substring(suffixIndex + 1));
                }
                if (!"\\".equals(path) || ("\\".equals(path) && !"temporary".equals(file.getName()))) {
                    fileInfoList.add(fileInfo);
                }
            }
        }
        return new Result().ok(fileInfoList);
    }

    /**
     * 按文件名称排序
     *
     * @param files
     */
    public static List<File> orderByName(File[] files) {
        List<File> fileList = Arrays.asList(files);
        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isDirectory() && o2.isFile())
                    return -1;
                if (o1.isFile() && o2.isDirectory())
                    return 1;
                return o1.getName().compareTo(o2.getName());
            }
        });
        return fileList;
    }

    /**
     * 文件信息
     *
     * @param params
     * @return
     */
    @GetMapping("fileInfo")
    public Result fileInfo(@RequestParam Map<String, String> params) {
        String path = params.get("path");
        if (StringUtils.isBlank(path)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);

        File file = new File(workspace);
        if (!file.exists()) {
            return new Result().error("文件不存在");
        }
        JSONObject result = new JSONObject();
        BasicFileAttributes attr = null;
        try {
            attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建时间
        Instant createInstant = attr.creationTime().toInstant();
        // 更新时间
        Instant updateInstant = attr.lastModifiedTime().toInstant();
        // 上次访问时间
        Instant lastVisitInstant = attr.lastAccessTime().toInstant();
        String createInstantDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()).format(createInstant);
        String updateInstantDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()).format(updateInstant);
        String lastVisitDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()).format(lastVisitInstant);
        result.put("createInstantDateFormat", createInstantDateFormat);
        result.put("updateInstantDateFormat", updateInstantDateFormat);
        result.put("lastVisitDateFormat", lastVisitDateFormat);
        return new Result().ok(result);
    }

    /**
     * 文件信息
     *
     * @param params
     * @return
     */
    @GetMapping("fileInfoMx")
    public Result fileInfoMx(@RequestParam Map<String, String> params) {
        String path = params.get("path");
        if (StringUtils.isBlank(path)) {
            return new Result().error("缺少参数");
        }
        //路径
        String workspace = ossService.getWorkspaceAndPath(path);

        File file = new File(workspace);
        if (!file.exists()) {
            return new Result().error("文件不存在");
        }
        JSONObject result = new JSONObject();
        result.put("size", com.shouyun.common.utils.FileUtils.getSize(file));
        if (file.isDirectory()) {
            result.put("fileCount", com.shouyun.common.utils.FileUtils.getFileCounts(file));
            result.put("dirCont", com.shouyun.common.utils.FileUtils.getDirCounts(file));
        } else {
//            result.put("md5", SecureUtil.md5(file));
        }
        return new Result().ok(result);
    }

    /**
     * 上传文件
     *
     * @param request
     * @param chunk
     * @return
     * @throws Exception
     */
    @PostMapping("upload")
    public Result upload(HttpServletRequest request, Chunk chunk) throws Exception {
        try {
            MultipartFile file = chunk.getFile();

            if (file == null) {
                return new Result().error("缺少文件");
            }

            //获取参数
            JSONObject sysParams = DataUtils.getData(DataUtils.PARAMS, "sys");
            String workspace = sysParams.getString("workspace");
            //临时文件路径
            String tempFileDirPath = workspace + File.separator + "temporary" + File.separator + chunk.getIdentifier();
            //输出切片文件
            File outFile = new File(tempFileDirPath + File.separator + chunk.getFilename() + "-" + chunk.getChunkNumber());
            InputStream inputStream = file.getInputStream();
            FileUtils.copyInputStreamToFile(inputStream, outFile);

            return new Result();
        } catch (Exception e) {
            e.printStackTrace();
            return new Result().error("系统错误");
        }
    }

    /**
     * 合并文件
     *
     * @param chunk
     * @return
     * @throws Exception
     */
    @PostMapping("merge")
    public Result mergePost(@RequestBody Chunk chunk) throws Exception {
        //获取参数
        JSONObject sysParams = DataUtils.getData(DataUtils.PARAMS, "sys");
        String workspace = sysParams.getString("workspace");

        //临时文件路径
        String tempFileDirPath = workspace + File.separator + "temporary" + File.separator + chunk.getIdentifier();

        //判断所有分片是否全部上传完成，完成就合并
        File dir = new File(tempFileDirPath);
        File[] files = dir.listFiles();
        if (files.length == chunk.getTotalChunks()) {
            String filePath = mergeFile(chunk, tempFileDirPath, workspace); //合并文件
            return new Result().ok(filePath);
        } else {
            return new Result().error("文件受损");
        }
    }

    /**
     * 下载文件
     *
     * @param path
     * @param request
     * @param response
     * @throws Exception
     */
    @GetMapping("download")
    public void download(String path, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StringUtils.isBlank(path)) {
            return;
        }
        path = java.net.URLDecoder.decode(path);
        path = ossService.getWorkspaceAndPath(path);
        File file = new File(path);
        ossService.download(file, response);
    }

    /**
     * 合并文件
     *
     * @param chunk
     * @param folder
     * @return
     */
    public String mergeFile(Chunk chunk, String folder, String workspace) throws Exception {
        String filename = chunk.getFilename(); //文件名
        String file = workspace + File.separator; //生成文件名
        if (StringUtils.isNotBlank(chunk.getRelativePath())) {
            file += chunk.getRelativePath();
        }
        file += filename;
        com.shouyun.common.utils.FileUtils.deleteFile(file);
        //合并
        merge(file, folder);
        //删除已上传的文件
        com.shouyun.common.utils.FileUtils.delete(folder);
        return file; //返回相对路径
    }

    /**
     * 合并
     *
     * @param targetFile 输出文件
     * @param folder     目标文件夹
     */
    public void merge(String targetFile, String folder) throws Exception {
        Files.createFile(Paths.get(targetFile));
        Files.list(Paths.get(folder))
                .filter(path -> path.getFileName().toString().contains("-"))
                .sorted((o1, o2) -> {
                    String p1 = o1.getFileName().toString();
                    String p2 = o2.getFileName().toString();
                    int i1 = p1.lastIndexOf("-");
                    int i2 = p2.lastIndexOf("-");
                    return Integer.valueOf(p2.substring(i2)).compareTo(Integer.valueOf(p1.substring(i1)));
                }).forEach(path -> {
                    try {
                        //以追加的形式写入文件
                        Files.write(Paths.get(targetFile), Files.readAllBytes(path), StandardOpenOption.APPEND);
                        //合并后删除该块
//                Files.delete(path);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    @LogOperation("删除")
    public Result delete(@RequestBody Long[] ids) {

        return new Result();
    }

}